package com.yike.user.lkl;

import com.lkl.laop.sdk.Config;
import com.lkl.laop.sdk.LKLSDK;
import com.lkl.laop.sdk.exception.SDKException;
import com.yike.common.config.AuthHeaderParser;
import com.yike.common.request.lkl.LklAuthHeader;
import lombok.Data;
import org.apache.commons.codec.binary.Base64;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.file.Files;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.*;

/***
 * @Description 功能描述：使用Java配置方式初始化SDK
 * @Date 2023/7/19 15:41
 */
@Data
public class BaseCommon {

    private static final String appId = "OP00000003"; // 拉卡拉appId
    private static final String serialNo = "00dfba8194c41b84cf"; // 你的证书序列号
    /**
     * 商户私钥信息地址
     */
    private static final String priKeyPath = getPath("lkl/OP00000003_private_key.pem"); //"lkl-zf-bs-laop-java-sdk-sample/src/main/resources/OP00000003商户私钥.txt";
    /**
     * 拉卡拉支付平台证书地址
     */
    private static final String lklCerPath = getPath("lkl/lkl-apigw-v2.cer"); //"lkl-zf-bs-laop-java-sdk-sample/src/main/resources/lakala开放平台证书.cer";
    /**
     * 拉卡拉支付平台证书地址2(用于拉卡拉通知验签)
     */
    private static final String lklNotifyCerPath = getPath("lkl/lkl-apigw-v2.cer"); //"lkl-zf-bs-laop-java-sdk-sample/src/main/resources/lakala开放平台证书.cer";
    /**
     * 拉卡拉报文加密对称性密钥
     */
    private static final String sm4Key = "uIj6CPg1GZAY10dXFfsEAQ==";
    /**
     * 服务地址
     */
    private static final String serverUrl = "https://test.wsmsd.cn/sit";

    private static volatile boolean init = false;


    /***
     * @Description: 初始化设置商户公共参数（全局只需设置一次）
     * @throws Exception
     */
    public static void doInit() throws Exception {
        if (!init) {
            init = initByJava();
        }
    }

    public static boolean initByJava() throws SDKException {
        Config config = new Config();
        config.setAppId(appId);
        config.setSerialNo(serialNo);
        config.setPriKeyPath(priKeyPath);
        config.setLklCerPath(lklCerPath);
        config.setLklNotifyCerPath(lklNotifyCerPath);
        config.setServerUrl(serverUrl);
        config.setSm4Key(sm4Key);
        return LKLSDK.init(config);

    }

    private static String getPath(String resourceName) {
        try {
            URL url = BaseCommon.class.getClassLoader().getResource(resourceName);
            if (url == null) {
                throw new FileNotFoundException(resourceName + " not found in classpath");
            }
            return URLDecoder.decode(url.getPath(), "UTF-8");
        } catch (Exception e) {
            throw new RuntimeException("找不到资源文件: " + resourceName, e);
        }
    }

    /**
     * 签名验证
     *
     * @param authorization 请求头中的Authorization字段
     * @param body          请求主体
     * @return
     */
    public static boolean signVerification(String authorization, String body) throws IOException, URISyntaxException {

        LklAuthHeader lklAuthHeader = AuthHeaderParser.parse(authorization);
        String preSignData = lklAuthHeader.getTimestamp() + "\n" + lklAuthHeader.getNonceStr() + "\n" + body + "\n";
        URL fileUrl = BaseCommon.class.getClassLoader().getResource("lkl/lkl-apigw-v2.cer");
        X509Certificate lklCertificate = loadCertificate(Files.newInputStream(new File(fileUrl.getFile()).toPath()));

        boolean verify = verify(lklCertificate, preSignData.getBytes("utf-8"), lklAuthHeader.getSignature());
        return verify;
    }


    private static boolean verify(X509Certificate certificate, byte[] message, String signature) {
        try {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initVerify(certificate);
            sign.update(message);
            byte[] signatureB = Base64.decodeBase64(signature);
            return sign.verify(signatureB);

        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
        } catch (SignatureException e) {
            throw new RuntimeException("签名验证过程发生了错误", e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException("无效的证书", e);
        }
    }

    /**
     * 获取证书信息
     *
     * @param inputStream
     * @return
     */
    public static X509Certificate loadCertificate(InputStream inputStream) {
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
            String publicKeyBase64 = Base64.encodeBase64String(cert.getPublicKey().getEncoded());
            System.out.println(publicKeyBase64);
            cert.checkValidity();
            return cert;
        } catch (CertificateExpiredException e) {
            throw new RuntimeException("证书已过期", e);
        } catch (CertificateNotYetValidException e) {
            throw new RuntimeException("证书尚未生效", e);
        } catch (CertificateException e) {
            throw new RuntimeException("无效的证书", e);
        }
    }

}
